﻿using System.Diagnostics;
using System.Windows.Media;

using Game.Common;
using Game.Level;
using Game.Map;
using Game.Map.Extensions;
using Game.Objects;
using Game.Actions;

namespace Game.Command.Internal
{
    class UnitAttacksUnit : UnitAttacksSomething
    {
        readonly IMapField _AttackedField;
        readonly Vehicle _AttackedUnit;
        readonly IGameMapView _AttackedView;
        readonly bool _Respond;
        
        public UnitAttacksUnit(
            IGameMapView gameMap,
            GameLevels levels,
            IMapField attackingField,
            IMapField attackedField, 
            IGameMapView attackedView,
            bool respond = true)
            : base(gameMap, levels, attackingField)
        {
            _AttackedField = attackedField;
            _AttackedUnit = attackedField.VehicleX().Vehicle;
            _Respond = respond;
            _AttackedView = attackedView;
            
            Setup(attackingField,attackedField,respond);
        }
        
        public GamePlayer DefendingPlayer
        {
            get { return _AttackedUnit.Owner; }
        }
        
        public Vehicle Target
        {
            get { return _AttackedUnit; }
        }
        
        void Setup (IMapField attackingField,
                    IMapField attackedField,
                    bool respond = true)
        {
            var attacking = attackingField.VehicleX().Vehicle;
            Debug.Assert(attacking != null, "attacking != null");
            var weap = attacking.Weapon;
            
            FightValues av = AttackValues;
            FightValues dv = DefendValues;
            
            av.strength     = weap.WeaponType.TargetingAccuracy / 100;
            av.armor        = attacking.Armor;
            av.damage       = attacking.Damage;
            av.experience   = attacking.Experience;
            av.hemming      = 1;
            av.weapcount    = attacking.Weapon.Ammo;
            av.brush        = new SolidColorBrush(attacking.Owner.Color);
            av.kamikaze     = false;
            av.attackbonus  = attackingField.TerrianX().AttackBonus;
            av.defensebonus = attackingField.TerrianX().DefenseBonus;
            
            var attackedunit = attackedField.VehicleX().Vehicle;
            var attachedFieldView = 
                _AttackedView.ViewFields[attackedField.Point];
            
            if ( respond  && !av.kamikaze  && attachedFieldView.IsVisible )
            {
                Debug.Assert(attackedunit != null, "attackedunit != null");
                dv.strength  =  
                        attackedunit.Weapon.Strength
                        * attackedunit.VehicleType.TargetingAccuracy / 100 
                     ;
                
                dv.weapcount = attackedunit.Weapon.Ammo;
                dv.attackbonus = attackedField.TerrianX().AttackBonus;
                dv.defensebonus = attackedField.TerrianX().DefenseBonus;
            }
            else
            {
                dv.strength = 0;
                dv.attackbonus = 0;
            }
            
            dv.armor = attackedunit.Weapon.Ammo;
            dv.damage = attackedunit.Damage;
            dv.experience = attackedunit.Experience;
            
            dv.hemming = strength_hemming(
                    attackingField.Point.X, attackingField.Point.Y, 
                    attackedField.Point );
            dv.defensebonus = attackedField.TerrianX().DefenseBonus;
            
            dv.brush = new SolidColorBrush(attackedunit.Owner.Color);
            dv.kamikaze = false;
            
            AttackValues = av;
            DefendValues = dv;
        }

        public override void SetResult(
            GameTurn turn,
            ActionExecutor executor)
        {
            FightValues av = AttackValues;
            FightValues dv = DefendValues;
            
            AttackingUnit.Experience = av.experience;
            AttackingUnit.Weapon.Ammo = av.weapcount;
            
            _AttackedUnit.Damage = dv.damage;
            AttackingUnit.Damage = av.damage;
            
            if ( _Respond ) 
            {
                _AttackedUnit.Experience = dv.experience;
                _AttackedUnit.Weapon.Ammo = dv.weapcount;
            }
                
            // If the attacking vehicle was destroyed, remove it 
            if ( AttackingUnit.Damage >= 100 ) 
            {
                var d = new DestructContainer(AttackingField);
                executor.ExecuteLater(GameMap, GameLevels, turn, d);
            }
            
            // If the attacked vehicle was destroyed, remove it 
            if ( _AttackedUnit.Damage >= 100 ) 
            {
                var d = new DestructContainer(_AttackedField);
                executor.ExecuteLater(GameMap, GameLevels, turn, d);
            }
        }
    }
 }
